<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h3>Closure</h3>
		<ul>
			<li>closure允许一个函数访问其他函数作用域中的数据</li>
			<li>这些函数处于同一个闭包中</li>
			<li><button onclick="funcTest1()">运行例子</button></li>
		</ul>
		<script>
			function funcTest1(){
				var arr = [1,2,3,4,5];
				var total = 0;
				arr.forEach(function processItem(item){
					total += item;				// 在funcion中可以访问在function外定义的total变量
				});
				console.log(total);
			}
			
		</script>
		
		<h3>返回函数</h3>
		<ul>
			<li>通过一个函数返回另一个函数，是JS中的常用手法</li>
			<li>在内部被返回的函数中，可以访问外部函数中定义的数据</li>
			<li><button onclick="funcTest2()">运行例子</button></li>
		</ul>
		<script>
			function createCompareFunc(propName){
				return function(object1, object2){
					var value1 = object1[propName];	// 在内部函数中仍然可以使用外部函数中的数据propName
					var value2 = object2[propName];
					if(value1 > value2){
						return 1;
					} else if(value1 < value2){
						return -1;
					}
					return 0;
				}
			}
			function funcTest2(){
				var employees = [
					{id:1001, name:'jerry', age:30},
					{id:1002, name:'jam', age:31},
					{id:1003, name:'david', age:35}
				];
				employees.sort(createCompareFunc("name"));
				for(var i=0;i<3;i++){
					var emp = employees[i];
					console.log("id:" + emp.id + ",name:" + emp.name + ",age:" + emp.age);
				}
			}
		</script>
		
		<h3>不同函数中的this</h3>
		<ul>
			<li>在回掉函数中的this与外部调用函数的this往往不是同一个对象</li>
			<li><button onclick="funcTest3()">运行例子</button></li>
		</ul>
		<script>
			function funcTest3(){
				console.log(this == window);		// 在funcTest3中,this就是window
				
				var req = new XMLHttpRequest();
				var url = window.location.href;
				
				req.onreadystatechange = function(){
					if(req.readyState == 4){
						var result = (req.status == 200) ? true : false;
						console.log("接收到响应：" + result);
						console.log(this == req);	// this并非window，而是req对象本身
					}
				}
				req.open("GET", url);
				req.send();
				console.log("请求已发送");
			}
		</script>
		
		<h3>保存外部函数的this对象</h3>
		<ul>
			<li>如果函数需要回调，则在进入回掉函数前，应将this保存到另一个变量中</li>
			<li>回调函数中的this已经不是调用者中的this</li>
			<li><button onclick="funcTest4()">运行例子</button></li>
		</ul>
		<script>
			function PageDownloader(url){
				this.url = url;
				this.result = false;
				this.data = "";
				this.done = false;
				
				PageDownloader.prototype.download = function(callback){
					var req = new XMLHttpRequest();
					var url = window.location.href;
					var self = this;				// this代表当前PageDownloader对象实例
					req.onreadystatechange = function(){
						if(req.readyState == 4){
							// this代表xmlhttpresquest对象，因此必须通过closure使用之前保存的self对象
							self.result = (req.status == 200) ? true : false;
							self.data = req.responseText;
							self.done = true;
							callback();
						}
					}
					req.open("GET", url);
					req.send();
				}
			}
			function funcTest4(){
				var url = window.location.href;
				var d = new PageDownloader(url);
				d.download(function(){			// 下载完毕后调用此回调函数
					console.log("result:" + d.result);
					console.log("data:" + d.data);	
				});
				
			}
		</script>
	</body>
</html>
